/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../config/head.h"
#include "../logger/head.h"
#include "../msg/head.h"
#include "helper_log.h"
#include "hook.h"
#include "mgr.h"

namespace xos_log
{

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static xos_container::i_container* container_ptr = 0;
    static xos_box::i_callback* callback_ptr = 0;
    static mgr* mgr_ptr = 0;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    mgr::mgr()
    {
        init_data();
    }

    mgr::~mgr()
    {
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::static_init( xos_container::i_container* pContainer, i_log_mgr** ppv )
    {
        return xos_stl::static_init_module( pContainer, ppv, container_ptr, mgr_ptr );
    }

    xos_container::i_container* mgr::container()
    {
        return container_ptr;
    }

    xos_box::i_callback* mgr::callback()
    {
        return callback_ptr;
    }

    mgr* mgr::get()
    {
        return mgr_ptr;
    } 

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // 设置公共线程，所有日志消息都扔到这个线程中处理。公用线程能节省，少用一些线程，代码也清楚一些
    // 
    int mgr::set_work_thread( xos_box::i_callback * pWorkThread )
    {
        int ret = 0;
        callback_ptr = pWorkThread;
        return ret;
    }

    // 
    // 添加日志输出方式
    // 
    int mgr::add_logger( i_logger * pLogger )
    {
        int nRet = 0;

        logger::T * p = logger::get_item_from_pool();
        p->init();
        p->m_pLogger = pLogger;
        logger::list()->push_back( p );

        return nRet;
    }

    // 
    // 创建日志输出方式
    // 

    i_log_file* mgr::file()
    {
        log_file::T* pRet = 0;
        xos_stl::init_item( pRet );
        return pRet;
    }

    i_logger* mgr::debug()
    {
        log_debug::T* pRet = 0;
        xos_stl::init_item( pRet );
        return pRet;
    }

    i_logger* mgr::cmd()
    {
        log_cmd::T* pRet = 0;
        xos_stl::init_item( pRet );
        return pRet;
    }

    int mgr::notify( i_log_msg *& pMsg )
    {
        int ret = 0;
        log_msg * pLogMsg = (log_msg *)pMsg;
        notify( enumMsg::MSG_ASYNC_LOG, pLogMsg );
        return ret;
    }

    // 生成i_log_msg
    i_log_msg * mgr::msg()
    {
        log_msg::T * pMsg = 0;
        xos_stl::init_pool_item( pMsg );
        return pMsg;
    }

    // 
    // 日志开关
    // 
    int mgr::enable( bool bEnable )
    {
        int ret = 0;
        m_bEnableLog = bEnable;
        return ret;
    }

    int mgr::flush()
    {
        int ret = 0;
        log_msg * pMsg = 0;
        notify( enumMsg::MSG_FLUSH_LOG, pMsg );
        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // xos::i_runnable method
    // 
    int mgr::on_msg( xos_box::i_msg *& pMsg )
    {
        int ret = 0;

        enumMsg eMsg = (enumMsg)pMsg->get_msg( 0, 0 );

        switch( eMsg )
        {
        case enumMsg::MSG_FLUSH_LOG:
            {
                mgr::get()->helper_flush();
            }
            break;
        case enumMsg::MSG_ASYNC_LOG:
            {
                mgr::get()->proc( pMsg );
            }
            break;
        default:
            {
            }
            break;
        }

        xos_stl::release_interface( pMsg );

        return ret;
    }

    int mgr::helper_flush()
    {
        int ret = 0;

        for( logger::ITER i = logger::list()->begin(); i != logger::list()->end(); ++i )
        {
            logger * p = *i;
            p->m_pLogger->flush();
        }

        return ret;
    }

    int mgr::proc( xos_box::i_msg *& pMsg )
    {
        int ret = 0;

        log_msg * pLogMsg = 0;
        {
            pLogMsg = (log_msg *)pMsg->get_void( 0, 0 );
            pLogMsg->fmt_log();
            helper_log obj;
            ret = obj.proc( pLogMsg );
        }
        xos_stl::release_interface( pLogMsg );

        return ret;
    }

    // 
    // 通知线程写日志
    // 
    int mgr::notify( enumMsg eMsg, log_msg *& pLogMsg )
    {
        int ret = 0;

        xos_box::i_msg * pMsg = 0;

        if( 0 == ret )
        {
            pMsg = mgr::container()->box()->msg();
        }

        if( 0 == ret )
        {
            pMsg->set_msg( 0, (int)eMsg );
            pMsg->set_runnable( 0, on_msg );
            pMsg->set_void( 0, pLogMsg );
            mgr::callback()->notify(pMsg);
            pLogMsg = 0;
            pMsg = 0;
        }

        return ret;
    }

    int mgr::init_data()
    {
        int ret = 0;
        m_bEnableLog = true;
        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::put_back_to_pool()
    {
        int ret = 0;
        delete this;
        return ret;
    }

    int mgr::init()
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = hook::init();
        }

        return ret;
    }

    int mgr::term()
    {
        int ret = 0;
        hook::term();
        init_data();
        return ret;
    }

} // xos_log
